package com.hfi.security.core.social.qq.api;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.social.oauth2.AbstractOAuth2ApiBinding;
import org.springframework.social.oauth2.TokenStrategy;

import java.io.IOException;

/**
 * QQImpl执行的是第6步 获取用户信息 其是在第5步的基础上进行执行的
 * AbstractOAuth2ApiBinding中有accessToken 就是存储前5步结束后获取到的令牌的 每个用户获取到的令牌是不同的
 * 注意这个属性accessToken是类级别的全局变量，所以我们写的这个QQImpl并不是一个单例对象 针对每个用户 走完oauth流程之后 会为每个用户创建
 * 一个获取用户信息的Api的实现 在accessToken中存这个用户获取到的令牌
 *
 * AbstractOAuth2ApiBinding中有restTemplate 是因为第6步要向服务提供商发送http请求，restTemplate就是帮助我们发送http请求的
 * @author ChangLiang
 * @date 2019/8/20
 */
public class QQImpl extends AbstractOAuth2ApiBinding implements QQ {

    private Logger logger = LoggerFactory.getLogger(getClass());
    /**
     * 第三方应用想使用qq进行第三方登录，那要到qq互联上注册，注册之后会得到一个appId
     */
    private String appId;

    /**
     * 用户在qq系统中的唯一标识
     */
    private String openId;

    // 还有两个路径

    private static final String URL_GET_USER_INFO = "https://graph.qq.com/user/get_user_info?oauth_consumer_key=%s" +
            "&openid=%s";

    private static final String URL_GET_OPENID = "https://graph.qq.com/oauth2.0/me?access_token=%s";

    private ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 处理三个参数
     * @param accessToken 父类AbstractOAuth2ApiBinding中有
     * @param appId 外部传入
     */
    public QQImpl(String accessToken, String appId) {
        // AbstractOAuth2ApiBinding 会自动帮我们处理query parameter named "access_token" 无需我们处理
        super(accessToken, TokenStrategy.OAUTH_TOKEN_PARAMETER);
        this.appId = appId;
        String url = String.format(URL_GET_OPENID, accessToken);
        String result = getRestTemplate().getForObject(url, String.class);
        logger.info("拿着access token换取openid:{}",result);
        this.openId = StringUtils.substringBetween(result, "\"openid\":\"", "\"}");
    }

    @Override
    public QQUserInfo getUserInfo(){
        String url = String.format(URL_GET_USER_INFO, appId, openId);
        String result = getRestTemplate().getForObject(url, String.class);
        logger.info("拿着app id和openid获取用户信息:{}",result);
        try {
            QQUserInfo qqUserInfo = objectMapper.readValue(result, QQUserInfo.class);
            qqUserInfo.setOpenId(this.openId);
            return qqUserInfo;
        } catch (IOException e) {
            throw new RuntimeException("获取用户信息失败");
        }
    }
}
